﻿using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace LogFileSystem.Controllers
{
    [ApiController]
    [Route("api/logs1")]
    public class Logs1Controller : ControllerBase
    {
        // 日志根目录（项目目录下的Logs文件夹）
        private readonly string _logRootPath;

        public Logs1Controller()
        {
            // 获取项目根目录下的Logs文件夹路径
            _logRootPath = Path.Combine(AppContext.BaseDirectory, "Logs");

            // 确保日志目录存在
            if (!Directory.Exists(_logRootPath))
            {
                Directory.CreateDirectory(_logRootPath);
            }
        }

        /// <summary>
        /// 获取所有日志级别文件夹（Info/Warn等）
        /// </summary>
        [HttpGet("levels")]
        public IActionResult GetLogLevels()
        {
            try
            {
                // 获取Logs目录下的所有子目录（日志级别）
                var levelDirectories = Directory.GetDirectories(_logRootPath)
                    .Select(dir => new
                    {
                        Level = Path.GetFileName(dir),
                        Path = dir
                    })
                    .OrderByDescending(d => d.Level)
                    .ToList();

                return Ok(levelDirectories);
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError,
                    new { message = "获取日志级别失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 获取指定级别下的日志文件列表
        /// </summary>
        [HttpGet("files/{level}")]
        public IActionResult GetLogFiles(string level)
        {
            try
            {
                // 构建级别目录路径
                var levelPath = Path.Combine(_logRootPath, level);

                // 验证目录是否存在
                if (!Directory.Exists(levelPath))
                {
                    return NotFound(new { message = $"日志级别 {level} 不存在" });
                }
               
                // 获取目录下的所有日志文件
                var logFiles = Directory.GetFiles(levelPath)
                    .Select(file => new LogFileInfo
                    {
                        FileName = Path.GetFileName(file),
                        Level = level,
                        FullPath = file,
                       
                        LastWriteTime = System.IO.File.GetLastWriteTime(file),
                        FileSize = new FileInfo(file).Length
                    })
                    .OrderByDescending(f => f.LastWriteTime)
                    .ToList();

                return Ok(logFiles);
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError,
                    new { message = "获取日志文件失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 读取日志文件内容（支持部分加载）
        /// </summary>
        [HttpGet("content/{level}/{fileName}")]
        public IActionResult GetLogContent(string level, string fileName, [FromQuery] int? maxLines = 1000)
        {
            try
            {
                // 构建完整文件路径
                var filePath = Path.Combine(_logRootPath, level, fileName);

                // 安全验证：确保文件在日志目录内（防止路径遍历攻击）
                if (!IsPathWithinRoot(filePath))
                {
                    return BadRequest(new { message = "无效的文件路径" });
                }

                // 验证文件是否存在
                if (!System.IO.File.Exists(filePath))
                {
                    return NotFound(new { message = $"日志文件 {fileName} 不存在" });
                }

                // 读取文件内容（大文件优化：只读取最后maxLines行）
                var content = ReadLogFileContent(filePath, maxLines ?? 1000);

                return Ok(new
                {
                    FileName = fileName,
                    Level = level,
                    Content = content,
                    LineCount = content.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Length
                });
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError,
                    new { message = "读取日志内容失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 下载日志文件
        /// </summary>
        [HttpGet("download/{level}/{fileName}")]
        public IActionResult DownloadLogFile(string level, string fileName)
        {
            try
            {
                // 构建完整文件路径
                var filePath = Path.Combine(_logRootPath, level, fileName);

                // 安全验证
                if (!IsPathWithinRoot(filePath) || !System.IO.File.Exists(filePath))
                {
                    return NotFound(new { message = $"日志文件 {fileName} 不存在" });
                }

                // 读取文件流
                var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

                // 返回文件供下载
                return File(fileStream, "text/plain", fileName);
            }
            catch (Exception ex)
            {
                return StatusCode(StatusCodes.Status500InternalServerError,
                    new { message = "下载日志文件失败", error = ex.Message });
            }
        }

        /// <summary>
        /// 安全验证：确保文件路径在日志根目录内
        /// </summary>
        private bool IsPathWithinRoot(string filePath)
        {
            var fullRootPath = Path.GetFullPath(_logRootPath);
            var fullFilePath = Path.GetFullPath(filePath);

            return fullFilePath.StartsWith(fullRootPath, StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// 读取日志文件内容（大文件优化）
        /// </summary>
        private string ReadLogFileContent(string filePath, int maxLines)
        {
            // 对于大文件，只读取最后N行，避免内存溢出
            if (new FileInfo(filePath).Length > 1024 * 1024 * 5) // 大于5MB的文件
            {
                return ReadLastLines(filePath, maxLines);
            }

            // 小文件直接读取全部内容
            return System.IO.File.ReadAllText(filePath);
        }

        /// <summary>
        /// 读取文件的最后N行
        /// </summary>
        private string ReadLastLines(string filePath, int lineCount)
        {
            if (lineCount <= 0)
                return "";

            using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (var sr = new StreamReader(fs))
            {
                // 从文件末尾开始查找
                byte[] buffer = new byte[1024];
                long position = fs.Length;
                int bytesRead;
                int linesFound = 0;
                string result = "";

                while (position > 0 && linesFound < lineCount)
                {
                    // 每次读取一块数据
                    int step = (int)Math.Min(buffer.Length, position);
                    position -= step;
                    fs.Position = position;
                    bytesRead = fs.Read(buffer, 0, step);
                    // 查找换行符
                    for (int i = bytesRead - 1; i >= 0; i--)
                    {
                        if (buffer[i] == '\n')
                        {
                            linesFound++;
                            if (linesFound == lineCount)
                            {
                                // 读取从当前位置到文件末尾的内容
                                fs.Position = position + i + 1;
                                result = sr.ReadToEnd();
                                return result;
                            }
                        }
                    }
                }

                // 如果文件行数不足，读取全部内容
                if (linesFound < lineCount)
                {
                    fs.Position = 0;
                    result = sr.ReadToEnd();
                }

                return result;
            }
        }
    }
    /// <summary>
    /// 日志文件信息DTO
    /// </summary>
    public class LogFileInfo
    {
        public string FileName { get; set; }
        public string Level { get; set; }
        public string FullPath { get; set; }
        public DateTime LastWriteTime { get; set; }
        public long FileSize { get; set; }

        // 计算文件大小的友好显示
        public string FileSizeDisplay => FormatFileSize(FileSize);

        private string FormatFileSize(long bytes)
        {
            if (bytes < 1024)
                return $"{bytes} B";
            else if (bytes < 1024 * 1024)
                return $"{(bytes / 1024.0).ToString("0.00")} KB";
            else if (bytes < 1024 * 1024 * 1024)
                return $"{(bytes / (1024.0 * 1024)).ToString("0.00")} MB";
            else
                return $"{(bytes / (1024.0 * 1024 * 1024)).ToString("0.00")} GB";
        }
    }
}
